//
//  ViewController.m
//  27-Block
//
//  Created by 曹曹 on 16/8/19.
//  Copyright © 2016年 曹曹. All rights reserved.
//

#import "ViewController.h"
#import "SecondViewController.h"

@interface ViewController ()
// block写在属性中
@property (nonatomic, copy) int (^testBlcok)(int, int);
// block写在方法中
- (void)handleData:(void (^)(void))block;
@property (retain, nonatomic) IBOutlet UILabel *textLabel;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
#pragma mark - 1.什么是block?
    // 消息传递机制之一
    // block与函数相似 - 有固定功能的代码段
#pragma mark - 2.blcok基本语法
    // int a;
    //  1>block的声明
    // 类型 void (^)(void) 变量名block
    // 返回值类型 (^block变量名)(参数列表)
    void (^block)(void);
    //  2>block赋值
    // block变量 = ^(参数列表) { 代码段 };
    block = ^(void) {
        
    };
#pragma mark - 3.block的形式
    // 有参有返回
    int (^sum)(int, int) = ^(int a, int b) {
        return a + b;
    };
    // 无参无返回
    void (^output0)(void) = ^(void) {
        NSLog(@"无参无返回值-----%s", __func__);
    };
#pragma mark - 无参无返回值的最简写法
    void (^output1)() = ^{
        NSLog(@"最简写法-----%s", __func__);
    };
    // 有参无返回
    void (^justParam)(int) = ^(int a) {
        NSLog(@"hello-----%d", a);
    };
    // 无参有返回
    // 系统提供的代码段 inlineBlock
    int(^justBack)() = ^ {
        return 0;
    };
#pragma mark - 4.block调用
    NSLog(@"%d", sum(3, 5));
    justBack();
    justParam(9);
    output0();
    output1();
#pragma mark - 5.系统中的block
    // 1.模态
    // 可以为空的block
    // (void (^ __nullable)(void))completion
//    [self presentViewController:[UIViewController] animated:YES completion:<#^(void)completion#>];
    // 2.GCD
    // typedef void (^dispatch_block_t)(void)
//    dispatch_sync(dispatch_get_main_queue(), ^{
//    });
    // 3.系统网络请求
    // 这个block不能为空
    // (void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler
//    [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"oo"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//    }];
#pragma mark - 6.block写在方法中
    // 属性block修饰符, 使用copy
    self.testBlcok = sum;
    self.testBlcok(10, 20);
    // 带block的方法调用
    [self handleData:^{
    }];
#pragma mark - 类型修饰符
    // __block  __weak  __strong
    //  1> __block
    // ARC和MRC下有区别
    // ARC和MRC下都可以进行下方操作
    // 可以在block内部修改外部变量
    // ARC下不能避免循环引用的问题(使用__weak才行)
    // MRC下可以
    int __block a = 0;
    __block int b = 0;
    void (^blockTest)() = ^{
        a = 100;
        b = 100;
    };
    blockTest();
    //  2> __weak 弱引用, 修饰block外的变量
    // 只能在ARC下使用, 避免block的循环引用
    //  3> __strong 强引用,
}
- (IBAction)pushNextVC:(id)sender {
    SecondViewController *secondVC = [[SecondViewController alloc] init];
    // 值传递, 需要实现block
    // 进入block前创建一个指针
    // 告诉block, 该指针弱引用, 可以被销毁
    SecondViewController * __block weakSecondVC = secondVC;
    weakSecondVC.passTitle = ^(NSString *title) {
        // block会对其内部的所有对象进行强引用
        self.textLabel.text = title;
        weakSecondVC.view.backgroundColor = [UIColor grayColor];
        // secondVC持有block, block强引用secondVC, 循环引用
    };
    [self.navigationController pushViewController:secondVC animated:YES];
    [secondVC release];
}

- (void)handleData:(void (^)(void))block {
    [[NSURLSession sharedSession] dataTaskWithRequest:[NSURLRequest new] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        block();
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
